/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ALKES_GFXFILTER_GRAPHICS_H_INCLUDED_
#define ALKES_GFXFILTER_GRAPHICS_H_INCLUDED_

#include "alkes/gfxfilter/internal.h"
#include "alkes/gfx/IGraphics3D.h"

namespace alkes {

/// \addtogroup gfxfilter
//@{

enum LogFilter
{
    AL_FILTER_IGraphicsflip = 0,
    AL_FILTER_IGraphicsresize,
    AL_FILTER_IGraphics2DcreateDefaultRenderTarget2D,
    AL_FILTER_IGraphics2DcreateDecoderFactory,
    AL_FILTER_IGraphics2DcreateImageBufferFactory,
    AL_FILTER_IGraphics2DcreateShape,
    AL_FILTER_IGraphics2DcreateLineShape,
    AL_FILTER_IGraphics2DcreateRectangleShape,
    AL_FILTER_IGraphics2DcreateImageShape,
    AL_FILTER_IGraphics2DcreatePolylineShape,
    AL_FILTER_IGraphics3DcreateDefaultRenderTarget3D,
    AL_FILTER_IGraphics3DcreateVertexBuffer,

    AL_FILTER_IRenderTarget2DbeginDraw2D,
    AL_FILTER_IRenderTarget2DendDraw2D,
    AL_FILTER_IRenderTarget2DgetTargetRect,
    AL_FILTER_IRenderTarget2DsetScissorRect,
    AL_FILTER_IRenderTarget2DgetScissorRect,
    AL_FILTER_IRenderTarget2DsetState,
    AL_FILTER_IRenderTarget2DgetState,
    AL_FILTER_IRenderTarget2DsetAlphaBlendMode,
    AL_FILTER_IRenderTarget2DgetAlphaBlendMode,
    AL_FILTER_IRenderTarget2DsetTextureFilter,
    AL_FILTER_IRenderTarget2DgetTextureFilter,
    AL_FILTER_IRenderTarget2DsetTextureAddressMode,
    AL_FILTER_IRenderTarget2DgetTextureAddressMode,
    AL_FILTER_IRenderTarget2Dfill,
    AL_FILTER_IRenderTarget2DdrawShape,
    AL_FILTER_IRenderTarget2DpushMatrix,
    AL_FILTER_IRenderTarget2DpopMatrix,
    AL_FILTER_IRenderTarget2Dtranslate,
    AL_FILTER_IRenderTarget2Dscale,
    AL_FILTER_IRenderTarget2Drotate,
    AL_FILTER_IRenderTarget2DskewX,
    AL_FILTER_IRenderTarget2DskewY,

    AL_FILTER_IRenderTarget3DbeginDraw3D,
    AL_FILTER_IRenderTarget3DendDraw3D,
    AL_FILTER_IRenderTarget3DsetViewport,
    AL_FILTER_IRenderTarget3DgetViewport,
    AL_FILTER_IRenderTarget3DsetPerspective,
    AL_FILTER_IRenderTarget3DsetLookAt,
    AL_FILTER_IRenderTarget3Dtranslate,
    AL_FILTER_IRenderTarget3Dscale,
    AL_FILTER_IRenderTarget3Drotate,
    AL_FILTER_IRenderTarget3DsetColor,
    AL_FILTER_IRenderTarget3DgetColor,
    AL_FILTER_IRenderTarget3DclearBuffer,
    AL_FILTER_IRenderTarget3DdrawPrimitive,
    AL_FILTER_IRenderTarget3DsetTexture,
    AL_FILTER_IRenderTarget3DsetTextureFilter,
    AL_FILTER_IRenderTarget3DgetTextureFilter,
    AL_FILTER_IRenderTarget3DsetTextureAddressMode,
    AL_FILTER_IRenderTarget3DgetTextureAddressMode,

    AL_FILTER_MAX,
};



/** Decorator class of IGraphics3D interface.
*/
class AL_GF_EXPORT GfxFilterGraphics
    : public IGraphics3D
{
    AL_DECLARE_FILTER_CLASS(GfxFilterGraphics, IGraphics);

public:
    static GfxFilterGraphics* create(IGraphics3D* component);

    virtual void resize(uint16_t width, uint16_t height);
    virtual void flip();
    virtual IRenderTarget2D* createDefaultRenderTarget2D();
    virtual IRenderTarget3D* createDefaultRenderTarget3D();
    virtual IVertexBuffer* createVertexBuffer(uint32_t vertex_type);
    virtual DecoderFactory* createDecoderFactory();
    virtual ImageBufferFactory* createImageBufferFactory();
    virtual Shape* createShape(int32_t shape_type, uint32_t num);
    virtual LineShape* createLineShape(uint32_t num);
    virtual RectangleShape* createRectangleShape(uint32_t num);
    virtual ImageShape* createImageShape(uint32_t num);
    virtual PolylineShape* createPolylineShape(uint32_t num);

    void enableAllLogFilter();
    void disableAllLogFilter();
    void enableLogFilter(LogFilter filter);
    void disableLogFilter(LogFilter filter);
    bool isEnableLogFilter(LogFilter filter) const;

private:
    GfxFilterGraphics(IGraphics3D* component);
    virtual ~GfxFilterGraphics();

    virtual void destroy();

private:
    intrusive_ptr<IGraphics3D> component_;
    uint32_t log_filter_[4];
};

#if !defined(__GNUC__)
#define AL_LOG_INVOKED(classname, method, format, ...)  \
    AL_DBG("Invoked: ((%s*)0x%p)->%s " format, #classname, static_cast<void*>(component_), #method, __VA_ARGS__)
#else
#define AL_LOG_INVOKED(classname, method, format, ...)  \
    AL_DBG("Invoked: ((%s*)0x%p)->%s " format, #classname, static_cast<void*>(component_), #method, ##__VA_ARGS__)
#endif

#define AL_LOG_BEGIN_PARAM(type, is_array)  AL_DBG("Define: " #type " temporary %s = {", is_array ? "[]" : "")
#if !defined(__GNUC__)
#define AL_LOG_PARAM(format, ...)           AL_DBG("Define: " format, __VA_ARGS__)
#else
#define AL_LOG_PARAM(format, ...)           AL_DBG("Define: " format, ##__VA_ARGS__)
#endif
#define AL_LOG_END_PARAM()                  AL_DBG("Define: };")

#if !defined(__GNUC__)
#define AL_LOG_RETVAL(type, format, ...)    AL_DBG("Retval: (%s)" format, #type, __VA_ARGS__)
#else
#define AL_LOG_RETVAL(type, format, ...)    AL_DBG("Retval: (%s)" format, #type, ##__VA_ARGS__)
#endif

//@}

}

#endif
